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

Side by Side Diff: webkit/quota/quota_database.cc

Issue 7331006: 2nd try: Implement QM::GetOriginsModifiedSince for browser data deleter support (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: '' Created 9 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « webkit/quota/quota_database.h ('k') | webkit/quota/quota_database_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "webkit/quota/quota_database.h" 5 #include "webkit/quota/quota_database.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "app/sql/connection.h" 9 #include "app/sql/connection.h"
10 #include "app/sql/diagnostic_error_delegate.h" 10 #include "app/sql/diagnostic_error_delegate.h"
11 #include "app/sql/meta_table.h" 11 #include "app/sql/meta_table.h"
12 #include "app/sql/statement.h" 12 #include "app/sql/statement.h"
13 #include "app/sql/transaction.h" 13 #include "app/sql/transaction.h"
14 #include "base/auto_reset.h" 14 #include "base/auto_reset.h"
15 #include "base/bind.h"
15 #include "base/file_util.h" 16 #include "base/file_util.h"
16 #include "base/time.h" 17 #include "base/time.h"
17 #include "googleurl/src/gurl.h" 18 #include "googleurl/src/gurl.h"
18 #include "webkit/quota/special_storage_policy.h" 19 #include "webkit/quota/special_storage_policy.h"
19 20
21 namespace quota {
20 namespace { 22 namespace {
21 23
22 // Definitions for database schema. 24 // Definitions for database schema.
23 25
24 const int kCurrentVersion = 2; 26 const int kCurrentVersion = 3;
25 const int kCompatibleVersion = 2; 27 const int kCompatibleVersion = 2;
26 28
27 const char kOriginsTable[] = "Origins";
28 const char kHostQuotaTable[] = "HostQuotaTable"; 29 const char kHostQuotaTable[] = "HostQuotaTable";
29 const char kOriginLastAccessTable[] = "OriginLastAccessTable"; 30 const char kOriginInfoTable[] = "OriginInfoTable";
30 const char kGlobalQuotaKeyPrefix[] = "GlobalQuota-"; 31 const char kGlobalQuotaKeyPrefix[] = "GlobalQuota-";
31 const char kIsOriginTableBootstrapped[] = "IsOriginTableBootstrapped"; 32 const char kIsOriginTableBootstrapped[] = "IsOriginTableBootstrapped";
32 33
33 const struct {
34 const char* table_name;
35 const char* columns;
36 } kTables[] = {
37 { kHostQuotaTable,
38 "(host TEXT NOT NULL,"
39 " type INTEGER NOT NULL,"
40 " quota INTEGER,"
41 " UNIQUE(host, type))" },
42 { kOriginLastAccessTable,
43 "(origin TEXT NOT NULL,"
44 " type INTEGER NOT NULL,"
45 " used_count INTEGER,"
46 " last_access_time INTEGER,"
47 " UNIQUE(origin, type))" },
48 };
49
50 const struct {
51 const char* index_name;
52 const char* table_name;
53 const char* columns;
54 bool unique;
55 } kIndexes[] = {
56 { "HostIndex",
57 kHostQuotaTable,
58 "(host)",
59 false },
60 { "OriginLastAccessIndex",
61 kOriginLastAccessTable,
62 "(origin, last_access_time)",
63 false },
64 };
65
66 const int kTableCount = ARRAYSIZE_UNSAFE(kTables);
67 const int kIndexCount = ARRAYSIZE_UNSAFE(kIndexes);
68
69 class HistogramUniquifier { 34 class HistogramUniquifier {
70 public: 35 public:
71 static const char* name() { return "Sqlite.Quota.Error"; } 36 static const char* name() { return "Sqlite.Quota.Error"; }
72 }; 37 };
73 38
74 bool PrepareCachedStatement( 39 bool PrepareCachedStatement(
75 sql::Connection* db, const sql::StatementID& id, 40 sql::Connection* db, const sql::StatementID& id,
76 const char* sql, sql::Statement* statement) { 41 const char* sql, sql::Statement* statement) {
77 DCHECK(db && sql && statement); 42 DCHECK(db && sql && statement);
78 statement->Assign(db->GetCachedStatement(id, sql)); 43 statement->Assign(db->GetCachedStatement(id, sql));
(...skipping 10 matching lines...) Expand all
89 else if (type == quota::kStorageTypePersistent) 54 else if (type == quota::kStorageTypePersistent)
90 return std::string(kGlobalQuotaKeyPrefix) + "persistent"; 55 return std::string(kGlobalQuotaKeyPrefix) + "persistent";
91 NOTREACHED() << "Unknown storage type " << type; 56 NOTREACHED() << "Unknown storage type " << type;
92 return std::string(); 57 return std::string();
93 } 58 }
94 59
95 const int kCommitIntervalMs = 30000; 60 const int kCommitIntervalMs = 30000;
96 61
97 } // anonymous namespace 62 } // anonymous namespace
98 63
99 namespace quota { 64 // static
65 const QuotaDatabase::TableSchema QuotaDatabase::kTables[] = {
66 { kHostQuotaTable,
67 "(host TEXT NOT NULL,"
68 " type INTEGER NOT NULL,"
69 " quota INTEGER DEFAULT 0,"
70 " UNIQUE(host, type))" },
71 { kOriginInfoTable,
72 "(origin TEXT NOT NULL,"
73 " type INTEGER NOT NULL,"
74 " used_count INTEGER DEFAULT 0,"
75 " last_access_time INTEGER DEFAULT 0,"
76 " last_modified_time INTEGER DEFAULT 0,"
77 " UNIQUE(origin, type))" },
78 };
100 79
80 // static
81 const QuotaDatabase::IndexSchema QuotaDatabase::kIndexes[] = {
82 { "HostIndex",
83 kHostQuotaTable,
84 "(host)",
85 false },
86 { "OriginInfoIndex",
87 kOriginInfoTable,
88 "(origin)",
89 false },
90 { "OriginLastAccessTimeIndex",
91 kOriginInfoTable,
92 "(last_access_time)",
93 false },
94 { "OriginLastModifiedTimeIndex",
95 kOriginInfoTable,
96 "(last_modified_time)",
97 false },
98 };
99
100 struct QuotaDatabase::QuotaTableImporter {
101 bool Append(const QuotaTableEntry& entry) {
102 entries.push_back(entry);
103 return true;
104 }
105 std::vector<QuotaTableEntry> entries;
106 };
107
108 // Clang requires explicit out-of-line constructors for them.
109 QuotaDatabase::QuotaTableEntry::QuotaTableEntry() {}
110 QuotaDatabase::QuotaTableEntry::QuotaTableEntry(
111 const std::string& host,
112 StorageType type,
113 int64 quota)
114 : host(host),
115 type(type),
116 quota(quota) {
117 }
118
119 QuotaDatabase::OriginInfoTableEntry::OriginInfoTableEntry() {}
120 QuotaDatabase::OriginInfoTableEntry::OriginInfoTableEntry(
121 const GURL& origin,
122 StorageType type,
123 int used_count,
124 const base::Time& last_access_time,
125 const base::Time& last_modified_time)
126 : origin(origin),
127 type(type),
128 used_count(used_count),
129 last_access_time(last_access_time),
130 last_modified_time(last_modified_time) {
131 }
132
133 // QuotaDatabase ------------------------------------------------------------
101 QuotaDatabase::QuotaDatabase(const FilePath& path) 134 QuotaDatabase::QuotaDatabase(const FilePath& path)
102 : db_file_path_(path), 135 : db_file_path_(path),
103 is_recreating_(false), 136 is_recreating_(false),
104 is_disabled_(false) { 137 is_disabled_(false) {
105 } 138 }
106 139
107 QuotaDatabase::~QuotaDatabase() { 140 QuotaDatabase::~QuotaDatabase() {
108 if (db_.get()) { 141 if (db_.get()) {
109 db_->CommitTransaction(); 142 db_->CommitTransaction();
110 } 143 }
(...skipping 28 matching lines...) Expand all
139 return true; 172 return true;
140 } 173 }
141 174
142 bool QuotaDatabase::SetHostQuota( 175 bool QuotaDatabase::SetHostQuota(
143 const std::string& host, StorageType type, int64 quota) { 176 const std::string& host, StorageType type, int64 quota) {
144 DCHECK_GE(quota, 0); 177 DCHECK_GE(quota, 0);
145 if (!LazyOpen(true)) 178 if (!LazyOpen(true))
146 return false; 179 return false;
147 180
148 sql::Statement statement; 181 sql::Statement statement;
149 182 const char* kSql =
150 int64 dummy; 183 "INSERT OR REPLACE INTO HostQuotaTable"
151 if (GetHostQuota(host, type, &dummy)) { 184 " (quota, host, type)"
152 const char* kSql = 185 " VALUES (?, ?, ?)";
153 "UPDATE HostQuotaTable" 186 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
154 " SET quota = ?" 187 return false;
155 " WHERE host = ? AND type = ?";
156 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
157 return false;
158 } else {
159 const char* kSql =
160 "INSERT INTO HostQuotaTable"
161 " (quota, host, type)"
162 " VALUES (?, ?, ?)";
163 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
164 return false;
165 }
166 188
167 statement.BindInt64(0, quota); 189 statement.BindInt64(0, quota);
168 statement.BindString(1, host); 190 statement.BindString(1, host);
169 statement.BindInt(2, static_cast<int>(type)); 191 statement.BindInt(2, static_cast<int>(type));
170 if (!statement.Run()) 192 if (!statement.Run())
171 return false; 193 return false;
172 194
173 ScheduleCommit(); 195 ScheduleCommit();
174 return true; 196 return true;
175 } 197 }
176 198
177 bool QuotaDatabase::SetOriginLastAccessTime( 199 bool QuotaDatabase::SetOriginLastAccessTime(
178 const GURL& origin, StorageType type, base::Time last_access_time) { 200 const GURL& origin, StorageType type, base::Time last_access_time) {
179 if (!LazyOpen(true)) 201 if (!LazyOpen(true))
180 return false; 202 return false;
181 203
182 sql::Statement statement; 204 sql::Statement statement;
183 205
184 int used_count = 1; 206 int used_count = 1;
185 if (FindOriginUsedCount(origin, type, &used_count)) { 207 if (FindOriginUsedCount(origin, type, &used_count)) {
186 ++used_count; 208 ++used_count;
187 const char* kSql = 209 const char* kSql =
188 "UPDATE OriginLastAccessTable" 210 "UPDATE OriginInfoTable"
189 " SET used_count = ?, last_access_time = ?" 211 " SET used_count = ?, last_access_time = ?"
190 " WHERE origin = ? AND type = ?"; 212 " WHERE origin = ? AND type = ?";
191 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) 213 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
192 return false; 214 return false;
193 } else { 215 } else {
194 const char* kSql = 216 const char* kSql =
195 "INSERT INTO OriginLastAccessTable" 217 "INSERT INTO OriginInfoTable"
196 " (used_count, last_access_time, origin, type)" 218 " (used_count, last_access_time, origin, type)"
197 " VALUES (?, ?, ?, ?)"; 219 " VALUES (?, ?, ?, ?)";
198 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) 220 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
199 return false; 221 return false;
200 } 222 }
201 223
202 statement.BindInt(0, used_count); 224 statement.BindInt(0, used_count);
203 statement.BindInt64(1, last_access_time.ToInternalValue()); 225 statement.BindInt64(1, last_access_time.ToInternalValue());
204 statement.BindString(2, origin.spec()); 226 statement.BindString(2, origin.spec());
205 statement.BindInt(3, static_cast<int>(type)); 227 statement.BindInt(3, static_cast<int>(type));
206 if (!statement.Run()) 228 if (!statement.Run())
207 return false; 229 return false;
208 230
209 ScheduleCommit(); 231 ScheduleCommit();
210 return true; 232 return true;
211 } 233 }
212 234
213 bool QuotaDatabase::RegisterOrigins(const std::set<GURL>& origins, 235 bool QuotaDatabase::SetOriginLastModifiedTime(
214 StorageType type, 236 const GURL& origin, StorageType type, base::Time last_modified_time) {
215 base::Time last_access_time) {
216 if (!LazyOpen(true)) 237 if (!LazyOpen(true))
217 return false; 238 return false;
218 239
240 sql::Statement statement;
241
242 int dummy;
243 if (FindOriginUsedCount(origin, type, &dummy)) {
244 const char* kSql =
245 "UPDATE OriginInfoTable"
246 " SET last_modified_time = ?"
247 " WHERE origin = ? AND type = ?";
248 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
249 return false;
250 } else {
251 const char* kSql =
252 "INSERT INTO OriginInfoTable"
253 " (last_modified_time, origin, type) VALUES (?, ?, ?)";
254 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
255 return false;
256 }
257
258 statement.BindInt64(0, last_modified_time.ToInternalValue());
259 statement.BindString(1, origin.spec());
260 statement.BindInt(2, static_cast<int>(type));
261 if (!statement.Run())
262 return false;
263
264 ScheduleCommit();
265 return true;
266 }
267
268 bool QuotaDatabase::RegisterInitialOriginInfo(
269 const std::set<GURL>& origins, StorageType type) {
270 if (!LazyOpen(true))
271 return false;
272
219 typedef std::set<GURL>::const_iterator itr_type; 273 typedef std::set<GURL>::const_iterator itr_type;
220 for (itr_type itr = origins.begin(), end = origins.end(); 274 for (itr_type itr = origins.begin(), end = origins.end();
221 itr != end; ++itr) { 275 itr != end; ++itr) {
222 const char* kSql = 276 const char* kSql =
223 "INSERT OR IGNORE INTO OriginLastAccessTable" 277 "INSERT OR IGNORE INTO OriginInfoTable"
224 " (used_count, last_access_time, origin, type)" 278 " (origin, type) VALUES (?, ?)";
225 " VALUES (?, ?, ?, ?)";
226 sql::Statement statement; 279 sql::Statement statement;
227 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) 280 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
228 return false; 281 return false;
229 282
230 statement.BindInt(0, 0); // used_count 283 statement.BindString(0, itr->spec());
231 statement.BindInt64(1, last_access_time.ToInternalValue()); 284 statement.BindInt(1, static_cast<int>(type));
232 statement.BindString(2, itr->spec());
233 statement.BindInt(3, static_cast<int>(type));
234 if (!statement.Run()) 285 if (!statement.Run())
235 return false; 286 return false;
236 } 287 }
237 288
238 ScheduleCommit(); 289 ScheduleCommit();
239 return true; 290 return true;
240 } 291 }
241 292
242 bool QuotaDatabase::DeleteHostQuota( 293 bool QuotaDatabase::DeleteHostQuota(
243 const std::string& host, StorageType type) { 294 const std::string& host, StorageType type) {
(...skipping 10 matching lines...) Expand all
254 305
255 statement.BindString(0, host); 306 statement.BindString(0, host);
256 statement.BindInt(1, static_cast<int>(type)); 307 statement.BindInt(1, static_cast<int>(type));
257 if (!statement.Run()) 308 if (!statement.Run())
258 return false; 309 return false;
259 310
260 ScheduleCommit(); 311 ScheduleCommit();
261 return true; 312 return true;
262 } 313 }
263 314
264 bool QuotaDatabase::DeleteOriginLastAccessTime( 315 bool QuotaDatabase::DeleteOriginInfo(
265 const GURL& origin, StorageType type) { 316 const GURL& origin, StorageType type) {
266 if (!LazyOpen(false)) 317 if (!LazyOpen(false))
267 return false; 318 return false;
268 319
269 const char* kSql = 320 const char* kSql =
270 "DELETE FROM OriginLastAccessTable" 321 "DELETE FROM OriginInfoTable"
271 " WHERE origin = ? AND type = ?"; 322 " WHERE origin = ? AND type = ?";
272 323
273 sql::Statement statement; 324 sql::Statement statement;
274 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) 325 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
275 return false; 326 return false;
276 327
277 statement.BindString(0, origin.spec()); 328 statement.BindString(0, origin.spec());
278 statement.BindInt(1, static_cast<int>(type)); 329 statement.BindInt(1, static_cast<int>(type));
279 if (!statement.Run()) 330 if (!statement.Run())
280 return false; 331 return false;
(...skipping 16 matching lines...) Expand all
297 348
298 bool QuotaDatabase::GetLRUOrigin( 349 bool QuotaDatabase::GetLRUOrigin(
299 StorageType type, 350 StorageType type,
300 const std::set<GURL>& exceptions, 351 const std::set<GURL>& exceptions,
301 SpecialStoragePolicy* special_storage_policy, 352 SpecialStoragePolicy* special_storage_policy,
302 GURL* origin) { 353 GURL* origin) {
303 DCHECK(origin); 354 DCHECK(origin);
304 if (!LazyOpen(false)) 355 if (!LazyOpen(false))
305 return false; 356 return false;
306 357
307 const char* kSql = "SELECT origin FROM OriginLastAccessTable" 358 const char* kSql = "SELECT origin FROM OriginInfoTable"
308 " WHERE type = ?" 359 " WHERE type = ?"
309 " ORDER BY last_access_time ASC"; 360 " ORDER BY last_access_time ASC";
310 361
311 sql::Statement statement; 362 sql::Statement statement;
312 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) 363 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
313 return false; 364 return false;
314 statement.BindInt(0, static_cast<int>(type)); 365 statement.BindInt(0, static_cast<int>(type));
315 366
316 while (statement.Step()) { 367 while (statement.Step()) {
317 GURL url(statement.ColumnString(0)); 368 GURL url(statement.ColumnString(0));
318 if (exceptions.find(url) != exceptions.end()) 369 if (exceptions.find(url) != exceptions.end())
319 continue; 370 continue;
320 if (special_storage_policy && 371 if (special_storage_policy &&
321 special_storage_policy->IsStorageUnlimited(url)) 372 special_storage_policy->IsStorageUnlimited(url))
322 continue; 373 continue;
323 *origin = url; 374 *origin = url;
324 return true; 375 return true;
325 } 376 }
326 377
327 *origin = GURL(); 378 *origin = GURL();
328 return statement.Succeeded(); 379 return statement.Succeeded();
329 } 380 }
330 381
382 bool QuotaDatabase::GetOriginsModifiedSince(
383 StorageType type, std::set<GURL>* origins, base::Time modified_since) {
384 DCHECK(origins);
385 if (!LazyOpen(false))
386 return false;
387
388 const char* kSql = "SELECT origin FROM OriginInfoTable"
389 " WHERE type = ? AND last_modified_time > ?";
390
391 sql::Statement statement;
392 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
393 return false;
394 statement.BindInt(0, static_cast<int>(type));
395 statement.BindInt64(1, modified_since.ToInternalValue());
396
397 origins->clear();
398 while (statement.Step())
399 origins->insert(GURL(statement.ColumnString(0)));
400
401 return statement.Succeeded();
402 }
403
331 bool QuotaDatabase::IsOriginDatabaseBootstrapped() { 404 bool QuotaDatabase::IsOriginDatabaseBootstrapped() {
332 if (!LazyOpen(true)) 405 if (!LazyOpen(true))
333 return false; 406 return false;
334 407
335 int flag = 0; 408 int flag = 0;
336 return meta_table_->GetValue(kIsOriginTableBootstrapped, &flag) && flag; 409 return meta_table_->GetValue(kIsOriginTableBootstrapped, &flag) && flag;
337 } 410 }
338 411
339 bool QuotaDatabase::SetOriginDatabaseBootstrapped(bool bootstrap_flag) { 412 bool QuotaDatabase::SetOriginDatabaseBootstrapped(bool bootstrap_flag) {
340 if (!LazyOpen(true)) 413 if (!LazyOpen(true))
341 return false; 414 return false;
342 415
343 return meta_table_->SetValue(kIsOriginTableBootstrapped, bootstrap_flag); 416 return meta_table_->SetValue(kIsOriginTableBootstrapped, bootstrap_flag);
344 } 417 }
345 418
346 void QuotaDatabase::Commit() { 419 void QuotaDatabase::Commit() {
347 if (!db_.get()) 420 if (!db_.get())
348 return; 421 return;
349 422
350 // Note: for now this will be called only by ScheduleCommit, but when it 423 if (timer_.IsRunning())
351 // becomes untrue we should call timer_.Stop() here. 424 timer_.Stop();
352 DCHECK(!timer_.IsRunning());
353 425
354 db_->CommitTransaction(); 426 db_->CommitTransaction();
355 db_->BeginTransaction(); 427 db_->BeginTransaction();
356 } 428 }
357 429
358 void QuotaDatabase::ScheduleCommit() { 430 void QuotaDatabase::ScheduleCommit() {
359 if (timer_.IsRunning()) 431 if (timer_.IsRunning())
360 return; 432 return;
361 timer_.Start(base::TimeDelta::FromMilliseconds(kCommitIntervalMs), this, 433 timer_.Start(base::TimeDelta::FromMilliseconds(kCommitIntervalMs), this,
362 &QuotaDatabase::Commit); 434 &QuotaDatabase::Commit);
363 } 435 }
364 436
365 bool QuotaDatabase::FindOriginUsedCount( 437 bool QuotaDatabase::FindOriginUsedCount(
366 const GURL& origin, StorageType type, int* used_count) { 438 const GURL& origin, StorageType type, int* used_count) {
367 DCHECK(used_count); 439 DCHECK(used_count);
368 if (!LazyOpen(false)) 440 if (!LazyOpen(false))
369 return false; 441 return false;
370 442
371 const char* kSql = 443 const char* kSql =
372 "SELECT used_count FROM OriginLastAccessTable" 444 "SELECT used_count FROM OriginInfoTable"
373 " WHERE origin = ? AND type = ?"; 445 " WHERE origin = ? AND type = ?";
374 446
375 sql::Statement statement; 447 sql::Statement statement;
376 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) 448 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
377 return false; 449 return false;
378 450
379 statement.BindString(0, origin.spec()); 451 statement.BindString(0, origin.spec());
380 statement.BindInt(1, static_cast<int>(type)); 452 statement.BindInt(1, static_cast<int>(type));
381 if (!statement.Step() || !statement.Succeeded()) 453 if (!statement.Step() || !statement.Succeeded())
382 return false; 454 return false;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 return false; 494 return false;
423 } 495 }
424 496
425 // Start a long-running transaction. 497 // Start a long-running transaction.
426 db_->BeginTransaction(); 498 db_->BeginTransaction();
427 499
428 return true; 500 return true;
429 } 501 }
430 502
431 bool QuotaDatabase::EnsureDatabaseVersion() { 503 bool QuotaDatabase::EnsureDatabaseVersion() {
504 static const size_t kTableCount = ARRAYSIZE_UNSAFE(kTables);
505 static const size_t kIndexCount = ARRAYSIZE_UNSAFE(kIndexes);
432 if (!sql::MetaTable::DoesTableExist(db_.get())) 506 if (!sql::MetaTable::DoesTableExist(db_.get()))
433 return CreateSchema(); 507 return CreateSchema(db_.get(), meta_table_.get(),
508 kCurrentVersion, kCompatibleVersion,
509 kTables, kTableCount,
510 kIndexes, kIndexCount);
434 511
435 if (!meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion)) 512 if (!meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion))
436 return false; 513 return false;
437 514
438 if (meta_table_->GetCompatibleVersionNumber() > kCurrentVersion) { 515 if (meta_table_->GetCompatibleVersionNumber() > kCurrentVersion) {
439 LOG(WARNING) << "Quota database is too new."; 516 LOG(WARNING) << "Quota database is too new.";
440 return false; 517 return false;
441 } 518 }
442 519
443 if (meta_table_->GetVersionNumber() < kCurrentVersion) { 520 if (meta_table_->GetVersionNumber() < kCurrentVersion) {
444 // TODO(kinuko): Support schema upgrade. 521 if (!UpgradeSchema(meta_table_->GetVersionNumber()))
445 return ResetSchema(); 522 return ResetSchema();
446 } 523 }
447 524
448 #ifndef NDEBUG 525 #ifndef NDEBUG
449 DCHECK(sql::MetaTable::DoesTableExist(db_.get())); 526 DCHECK(sql::MetaTable::DoesTableExist(db_.get()));
450 for (int i = 0; i < kTableCount; ++i) { 527 for (size_t i = 0; i < kTableCount; ++i) {
451 DCHECK(db_->DoesTableExist(kTables[i].table_name)); 528 DCHECK(db_->DoesTableExist(kTables[i].table_name));
452 } 529 }
453 #endif 530 #endif
454 531
455 return true; 532 return true;
456 } 533 }
457 534
458 bool QuotaDatabase::CreateSchema() { 535 // static
536 bool QuotaDatabase::CreateSchema(
537 sql::Connection* database,
538 sql::MetaTable* meta_table,
539 int schema_version, int compatible_version,
540 const TableSchema* tables, size_t tables_size,
541 const IndexSchema* indexes, size_t indexes_size) {
459 // TODO(kinuko): Factor out the common code to create databases. 542 // TODO(kinuko): Factor out the common code to create databases.
460 sql::Transaction transaction(db_.get()); 543 sql::Transaction transaction(database);
461 if (!transaction.Begin()) 544 if (!transaction.Begin())
462 return false; 545 return false;
463 546
464 if (!meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion)) 547 if (!meta_table->Init(database, schema_version, compatible_version))
465 return false; 548 return false;
466 549
467 for (int i = 0; i < kTableCount; ++i) { 550 for (size_t i = 0; i < tables_size; ++i) {
468 std::string sql("CREATE TABLE "); 551 std::string sql("CREATE TABLE ");
469 sql += kTables[i].table_name; 552 sql += tables[i].table_name;
470 sql += kTables[i].columns; 553 sql += tables[i].columns;
471 if (!db_->Execute(sql.c_str())) { 554 if (!database->Execute(sql.c_str())) {
472 VLOG(1) << "Failed to execute " << sql; 555 VLOG(1) << "Failed to execute " << sql;
473 return false; 556 return false;
474 } 557 }
475 } 558 }
476 559
477 for (int i = 0; i < kIndexCount; ++i) { 560 for (size_t i = 0; i < indexes_size; ++i) {
478 std::string sql; 561 std::string sql;
479 if (kIndexes[i].unique) 562 if (indexes[i].unique)
480 sql += "CREATE UNIQUE INDEX "; 563 sql += "CREATE UNIQUE INDEX ";
481 else 564 else
482 sql += "CREATE INDEX "; 565 sql += "CREATE INDEX ";
483 sql += kIndexes[i].index_name; 566 sql += indexes[i].index_name;
484 sql += " ON "; 567 sql += " ON ";
485 sql += kIndexes[i].table_name; 568 sql += indexes[i].table_name;
486 sql += kIndexes[i].columns; 569 sql += indexes[i].columns;
487 if (!db_->Execute(sql.c_str())) { 570 if (!database->Execute(sql.c_str())) {
488 VLOG(1) << "Failed to execute " << sql; 571 VLOG(1) << "Failed to execute " << sql;
489 return false; 572 return false;
490 } 573 }
491 } 574 }
492 575
493 return transaction.Commit(); 576 return transaction.Commit();
494 } 577 }
495 578
496 bool QuotaDatabase::ResetSchema() { 579 bool QuotaDatabase::ResetSchema() {
497 DCHECK(!db_file_path_.empty()); 580 DCHECK(!db_file_path_.empty());
(...skipping 11 matching lines...) Expand all
509 return false; 592 return false;
510 593
511 // So we can't go recursive. 594 // So we can't go recursive.
512 if (is_recreating_) 595 if (is_recreating_)
513 return false; 596 return false;
514 597
515 AutoReset<bool> auto_reset(&is_recreating_, true); 598 AutoReset<bool> auto_reset(&is_recreating_, true);
516 return LazyOpen(true); 599 return LazyOpen(true);
517 } 600 }
518 601
602 bool QuotaDatabase::UpgradeSchema(int current_version) {
603 if (current_version == 2) {
604 QuotaTableImporter importer;
605 typedef std::vector<QuotaTableEntry> QuotaTableEntries;
606 if (!DumpQuotaTable(new QuotaTableCallback(base::Bind(
607 &QuotaTableImporter::Append, base::Unretained(&importer)))))
608 return false;
609 ResetSchema();
610 for (QuotaTableEntries::const_iterator iter = importer.entries.begin();
611 iter != importer.entries.end(); ++iter) {
612 if (!SetHostQuota(iter->host, iter->type, iter->quota))
613 return false;
614 }
615 Commit();
616 return true;
617 }
618 return false;
619 }
620
519 bool QuotaDatabase::DumpQuotaTable(QuotaTableCallback* callback) { 621 bool QuotaDatabase::DumpQuotaTable(QuotaTableCallback* callback) {
520 scoped_ptr<QuotaTableCallback> callback_deleter(callback); 622 scoped_ptr<QuotaTableCallback> callback_deleter(callback);
521 if (!LazyOpen(true)) 623 if (!LazyOpen(true))
522 return false; 624 return false;
523 625
524 const char* kSql = "SELECT * FROM HostQuotaTable"; 626 const char* kSql = "SELECT * FROM HostQuotaTable";
525 sql::Statement statement; 627 sql::Statement statement;
526 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) 628 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
527 return false; 629 return false;
528 630
529 while (statement.Step()) { 631 while (statement.Step()) {
530 QuotaTableEntry entry = { 632 QuotaTableEntry entry = QuotaTableEntry(
531 statement.ColumnString(0), 633 statement.ColumnString(0),
532 static_cast<StorageType>(statement.ColumnInt(1)), 634 static_cast<StorageType>(statement.ColumnInt(1)),
533 statement.ColumnInt64(2) 635 statement.ColumnInt64(2));
534 };
535 636
536 if (!callback->Run(entry)) 637 if (!callback->Run(entry))
537 return true; 638 return true;
538 } 639 }
539 640
540 return statement.Succeeded(); 641 return statement.Succeeded();
541 } 642 }
542 643
543 bool QuotaDatabase::DumpLastAccessTimeTable( 644 bool QuotaDatabase::DumpOriginInfoTable(
544 LastAccessTimeTableCallback* callback) { 645 OriginInfoTableCallback* callback) {
545 scoped_ptr<LastAccessTimeTableCallback> callback_deleter(callback); 646 scoped_ptr<OriginInfoTableCallback> callback_deleter(callback);
546 647
547 if (!LazyOpen(true)) 648 if (!LazyOpen(true))
548 return false; 649 return false;
549 650
550 const char* kSql = "SELECT * FROM OriginLastAccessTable"; 651 const char* kSql = "SELECT * FROM OriginInfoTable";
551 sql::Statement statement; 652 sql::Statement statement;
552 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) 653 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
553 return false; 654 return false;
554 655
555 while (statement.Step()) { 656 while (statement.Step()) {
556 LastAccessTimeTableEntry entry = { 657 OriginInfoTableEntry entry(
557 GURL(statement.ColumnString(0)), 658 GURL(statement.ColumnString(0)),
558 static_cast<StorageType>(statement.ColumnInt(1)), 659 static_cast<StorageType>(statement.ColumnInt(1)),
559 statement.ColumnInt(2), 660 statement.ColumnInt(2),
560 base::Time::FromInternalValue(statement.ColumnInt64(3)) 661 base::Time::FromInternalValue(statement.ColumnInt64(3)),
561 }; 662 base::Time::FromInternalValue(statement.ColumnInt64(4)));
562 663
563 if (!callback->Run(entry)) 664 if (!callback->Run(entry))
564 return true; 665 return true;
565 } 666 }
566 667
567 return statement.Succeeded(); 668 return statement.Succeeded();
568 } 669 }
569 670
570 bool operator<(const QuotaDatabase::QuotaTableEntry& lhs, 671 bool operator<(const QuotaDatabase::QuotaTableEntry& lhs,
571 const QuotaDatabase::QuotaTableEntry& rhs) { 672 const QuotaDatabase::QuotaTableEntry& rhs) {
572 if (lhs.host < rhs.host) return true; 673 if (lhs.host < rhs.host) return true;
573 if (rhs.host < lhs.host) return false; 674 if (rhs.host < lhs.host) return false;
574 if (lhs.type < rhs.type) return true; 675 if (lhs.type < rhs.type) return true;
575 if (rhs.type < lhs.type) return false; 676 if (rhs.type < lhs.type) return false;
576 return lhs.quota < rhs.quota; 677 return lhs.quota < rhs.quota;
577 } 678 }
578 679
579 bool operator<(const QuotaDatabase::LastAccessTimeTableEntry& lhs, 680 bool operator<(const QuotaDatabase::OriginInfoTableEntry& lhs,
580 const QuotaDatabase::LastAccessTimeTableEntry& rhs) { 681 const QuotaDatabase::OriginInfoTableEntry& rhs) {
581 if (lhs.origin < rhs.origin) return true; 682 if (lhs.origin < rhs.origin) return true;
582 if (rhs.origin < lhs.origin) return false; 683 if (rhs.origin < lhs.origin) return false;
583 if (lhs.type < rhs.type) return true; 684 if (lhs.type < rhs.type) return true;
584 if (rhs.type < lhs.type) return false; 685 if (rhs.type < lhs.type) return false;
585 if (lhs.used_count < rhs.used_count) return true; 686 if (lhs.used_count < rhs.used_count) return true;
586 if (rhs.used_count < lhs.used_count) return false; 687 if (rhs.used_count < lhs.used_count) return false;
587 return lhs.last_access_time < rhs.last_access_time; 688 return lhs.last_access_time < rhs.last_access_time;
588 } 689 }
690
589 } // quota namespace 691 } // quota namespace
OLDNEW
« no previous file with comments | « webkit/quota/quota_database.h ('k') | webkit/quota/quota_database_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698