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

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

Issue 7168019: Implement QM::GetOriginsModifiedSince for browser data deleter support (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: reflected comments 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 };
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 };
100 107
101 QuotaDatabase::QuotaDatabase(const FilePath& path) 108 QuotaDatabase::QuotaDatabase(const FilePath& path)
102 : db_file_path_(path), 109 : db_file_path_(path),
103 is_recreating_(false), 110 is_recreating_(false),
104 is_disabled_(false) { 111 is_disabled_(false) {
105 } 112 }
106 113
107 QuotaDatabase::~QuotaDatabase() { 114 QuotaDatabase::~QuotaDatabase() {
108 if (db_.get()) { 115 if (db_.get()) {
109 db_->CommitTransaction(); 116 db_->CommitTransaction();
(...skipping 29 matching lines...) Expand all
139 return true; 146 return true;
140 } 147 }
141 148
142 bool QuotaDatabase::SetHostQuota( 149 bool QuotaDatabase::SetHostQuota(
143 const std::string& host, StorageType type, int64 quota) { 150 const std::string& host, StorageType type, int64 quota) {
144 DCHECK_GE(quota, 0); 151 DCHECK_GE(quota, 0);
145 if (!LazyOpen(true)) 152 if (!LazyOpen(true))
146 return false; 153 return false;
147 154
148 sql::Statement statement; 155 sql::Statement statement;
149 156 const char* kSql =
150 int64 dummy; 157 "INSERT OR REPLACE INTO HostQuotaTable"
151 if (GetHostQuota(host, type, &dummy)) { 158 " (quota, host, type)"
152 const char* kSql = 159 " VALUES (?, ?, ?)";
153 "UPDATE HostQuotaTable" 160 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
154 " SET quota = ?" 161 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 162
167 statement.BindInt64(0, quota); 163 statement.BindInt64(0, quota);
168 statement.BindString(1, host); 164 statement.BindString(1, host);
169 statement.BindInt(2, static_cast<int>(type)); 165 statement.BindInt(2, static_cast<int>(type));
170 if (!statement.Run()) 166 if (!statement.Run())
171 return false; 167 return false;
172 168
173 ScheduleCommit(); 169 ScheduleCommit();
174 return true; 170 return true;
175 } 171 }
176 172
177 bool QuotaDatabase::SetOriginLastAccessTime( 173 bool QuotaDatabase::SetOriginLastAccessTime(
178 const GURL& origin, StorageType type, base::Time last_access_time) { 174 const GURL& origin, StorageType type, base::Time last_access_time) {
179 if (!LazyOpen(true)) 175 if (!LazyOpen(true))
180 return false; 176 return false;
181 177
182 sql::Statement statement; 178 sql::Statement statement;
183 179
184 int used_count = 1; 180 int used_count = 1;
185 if (FindOriginUsedCount(origin, type, &used_count)) { 181 if (FindOriginUsedCount(origin, type, &used_count)) {
186 ++used_count; 182 ++used_count;
187 const char* kSql = 183 const char* kSql =
188 "UPDATE OriginLastAccessTable" 184 "UPDATE OriginInfoTable"
189 " SET used_count = ?, last_access_time = ?" 185 " SET used_count = ?, last_access_time = ?"
190 " WHERE origin = ? AND type = ?"; 186 " WHERE origin = ? AND type = ?";
191 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) 187 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
192 return false; 188 return false;
193 } else { 189 } else {
194 const char* kSql = 190 const char* kSql =
195 "INSERT INTO OriginLastAccessTable" 191 "INSERT INTO OriginInfoTable"
196 " (used_count, last_access_time, origin, type)" 192 " (used_count, last_access_time, origin, type)"
197 " VALUES (?, ?, ?, ?)"; 193 " VALUES (?, ?, ?, ?)";
198 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) 194 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
199 return false; 195 return false;
200 } 196 }
201 197
202 statement.BindInt(0, used_count); 198 statement.BindInt(0, used_count);
203 statement.BindInt64(1, last_access_time.ToInternalValue()); 199 statement.BindInt64(1, last_access_time.ToInternalValue());
204 statement.BindString(2, origin.spec()); 200 statement.BindString(2, origin.spec());
205 statement.BindInt(3, static_cast<int>(type)); 201 statement.BindInt(3, static_cast<int>(type));
206 if (!statement.Run()) 202 if (!statement.Run())
207 return false; 203 return false;
208 204
209 ScheduleCommit(); 205 ScheduleCommit();
210 return true; 206 return true;
211 } 207 }
212 208
213 bool QuotaDatabase::RegisterOrigins(const std::set<GURL>& origins, 209 bool QuotaDatabase::SetOriginLastModifiedTime(
214 StorageType type, 210 const GURL& origin, StorageType type, base::Time last_modified_time) {
215 base::Time last_access_time) {
216 if (!LazyOpen(true)) 211 if (!LazyOpen(true))
217 return false; 212 return false;
218 213
214 sql::Statement statement;
215
216 int dummy;
217 if (FindOriginUsedCount(origin, type, &dummy)) {
218 const char* kSql =
219 "UPDATE OriginInfoTable"
220 " SET last_modified_time = ?"
221 " WHERE origin = ? AND type = ?";
222 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
223 return false;
224 } else {
225 const char* kSql =
226 "INSERT INTO OriginInfoTable"
227 " (last_modified_time, origin, type) VALUES (?, ?, ?)";
228 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
229 return false;
230 }
231
232 statement.BindInt64(0, last_modified_time.ToInternalValue());
233 statement.BindString(1, origin.spec());
234 statement.BindInt(2, static_cast<int>(type));
235 if (!statement.Run())
236 return false;
237
238 ScheduleCommit();
239 return true;
240 }
241
242 bool QuotaDatabase::RegisterInitialOriginInfo(
243 const std::set<GURL>& origins, StorageType type) {
244 if (!LazyOpen(true))
245 return false;
246
219 typedef std::set<GURL>::const_iterator itr_type; 247 typedef std::set<GURL>::const_iterator itr_type;
220 for (itr_type itr = origins.begin(), end = origins.end(); 248 for (itr_type itr = origins.begin(), end = origins.end();
221 itr != end; ++itr) { 249 itr != end; ++itr) {
222 const char* kSql = 250 const char* kSql =
223 "INSERT OR IGNORE INTO OriginLastAccessTable" 251 "INSERT OR IGNORE INTO OriginInfoTable"
224 " (used_count, last_access_time, origin, type)" 252 " (origin, type) VALUES (?, ?)";
225 " VALUES (?, ?, ?, ?)";
226 sql::Statement statement; 253 sql::Statement statement;
227 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) 254 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
228 return false; 255 return false;
229 256
230 statement.BindInt(0, 0); // used_count 257 statement.BindString(0, itr->spec());
231 statement.BindInt64(1, last_access_time.ToInternalValue()); 258 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()) 259 if (!statement.Run())
235 return false; 260 return false;
236 } 261 }
237 262
238 ScheduleCommit(); 263 ScheduleCommit();
239 return true; 264 return true;
240 } 265 }
241 266
242 bool QuotaDatabase::DeleteHostQuota( 267 bool QuotaDatabase::DeleteHostQuota(
243 const std::string& host, StorageType type) { 268 const std::string& host, StorageType type) {
(...skipping 10 matching lines...) Expand all
254 279
255 statement.BindString(0, host); 280 statement.BindString(0, host);
256 statement.BindInt(1, static_cast<int>(type)); 281 statement.BindInt(1, static_cast<int>(type));
257 if (!statement.Run()) 282 if (!statement.Run())
258 return false; 283 return false;
259 284
260 ScheduleCommit(); 285 ScheduleCommit();
261 return true; 286 return true;
262 } 287 }
263 288
264 bool QuotaDatabase::DeleteOriginLastAccessTime( 289 bool QuotaDatabase::DeleteOriginInfo(
265 const GURL& origin, StorageType type) { 290 const GURL& origin, StorageType type) {
266 if (!LazyOpen(false)) 291 if (!LazyOpen(false))
267 return false; 292 return false;
268 293
269 const char* kSql = 294 const char* kSql =
270 "DELETE FROM OriginLastAccessTable" 295 "DELETE FROM OriginInfoTable"
271 " WHERE origin = ? AND type = ?"; 296 " WHERE origin = ? AND type = ?";
272 297
273 sql::Statement statement; 298 sql::Statement statement;
274 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) 299 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
275 return false; 300 return false;
276 301
277 statement.BindString(0, origin.spec()); 302 statement.BindString(0, origin.spec());
278 statement.BindInt(1, static_cast<int>(type)); 303 statement.BindInt(1, static_cast<int>(type));
279 if (!statement.Run()) 304 if (!statement.Run())
280 return false; 305 return false;
(...skipping 16 matching lines...) Expand all
297 322
298 bool QuotaDatabase::GetLRUOrigin( 323 bool QuotaDatabase::GetLRUOrigin(
299 StorageType type, 324 StorageType type,
300 const std::set<GURL>& exceptions, 325 const std::set<GURL>& exceptions,
301 SpecialStoragePolicy* special_storage_policy, 326 SpecialStoragePolicy* special_storage_policy,
302 GURL* origin) { 327 GURL* origin) {
303 DCHECK(origin); 328 DCHECK(origin);
304 if (!LazyOpen(false)) 329 if (!LazyOpen(false))
305 return false; 330 return false;
306 331
307 const char* kSql = "SELECT origin FROM OriginLastAccessTable" 332 const char* kSql = "SELECT origin FROM OriginInfoTable"
308 " WHERE type = ?" 333 " WHERE type = ?"
309 " ORDER BY last_access_time ASC"; 334 " ORDER BY last_access_time ASC";
310 335
311 sql::Statement statement; 336 sql::Statement statement;
312 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) 337 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
313 return false; 338 return false;
314 statement.BindInt(0, static_cast<int>(type)); 339 statement.BindInt(0, static_cast<int>(type));
315 340
316 while (statement.Step()) { 341 while (statement.Step()) {
317 GURL url(statement.ColumnString(0)); 342 GURL url(statement.ColumnString(0));
318 if (exceptions.find(url) != exceptions.end()) 343 if (exceptions.find(url) != exceptions.end())
319 continue; 344 continue;
320 if (special_storage_policy && 345 if (special_storage_policy &&
321 special_storage_policy->IsStorageUnlimited(url)) 346 special_storage_policy->IsStorageUnlimited(url))
322 continue; 347 continue;
323 *origin = url; 348 *origin = url;
324 return true; 349 return true;
325 } 350 }
326 351
327 *origin = GURL(); 352 *origin = GURL();
328 return statement.Succeeded(); 353 return statement.Succeeded();
329 } 354 }
330 355
356 bool QuotaDatabase::GetOriginsModifiedSince(
357 StorageType type, std::set<GURL>* origins, base::Time modified_since) {
358 DCHECK(origins);
359 if (!LazyOpen(false))
360 return false;
361
362 const char* kSql = "SELECT origin FROM OriginInfoTable"
363 " WHERE type = ? AND last_modified_time > ?";
364
365 sql::Statement statement;
366 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
367 return false;
368 statement.BindInt(0, static_cast<int>(type));
369 statement.BindInt64(1, modified_since.ToInternalValue());
370
371 origins->clear();
372 while (statement.Step())
373 origins->insert(GURL(statement.ColumnString(0)));
374
375 return statement.Succeeded();
376 }
377
331 bool QuotaDatabase::IsOriginDatabaseBootstrapped() { 378 bool QuotaDatabase::IsOriginDatabaseBootstrapped() {
332 if (!LazyOpen(true)) 379 if (!LazyOpen(true))
333 return false; 380 return false;
334 381
335 int flag = 0; 382 int flag = 0;
336 return meta_table_->GetValue(kIsOriginTableBootstrapped, &flag) && flag; 383 return meta_table_->GetValue(kIsOriginTableBootstrapped, &flag) && flag;
337 } 384 }
338 385
339 bool QuotaDatabase::SetOriginDatabaseBootstrapped(bool bootstrap_flag) { 386 bool QuotaDatabase::SetOriginDatabaseBootstrapped(bool bootstrap_flag) {
340 if (!LazyOpen(true)) 387 if (!LazyOpen(true))
341 return false; 388 return false;
342 389
343 return meta_table_->SetValue(kIsOriginTableBootstrapped, bootstrap_flag); 390 return meta_table_->SetValue(kIsOriginTableBootstrapped, bootstrap_flag);
344 } 391 }
345 392
346 void QuotaDatabase::Commit() { 393 void QuotaDatabase::Commit() {
347 if (!db_.get()) 394 if (!db_.get())
348 return; 395 return;
349 396
350 // Note: for now this will be called only by ScheduleCommit, but when it 397 if (timer_.IsRunning())
351 // becomes untrue we should call timer_.Stop() here. 398 timer_.Stop();
352 DCHECK(!timer_.IsRunning());
353 399
354 db_->CommitTransaction(); 400 db_->CommitTransaction();
355 db_->BeginTransaction(); 401 db_->BeginTransaction();
356 } 402 }
357 403
358 void QuotaDatabase::ScheduleCommit() { 404 void QuotaDatabase::ScheduleCommit() {
359 if (timer_.IsRunning()) 405 if (timer_.IsRunning())
360 return; 406 return;
361 timer_.Start(base::TimeDelta::FromMilliseconds(kCommitIntervalMs), this, 407 timer_.Start(base::TimeDelta::FromMilliseconds(kCommitIntervalMs), this,
362 &QuotaDatabase::Commit); 408 &QuotaDatabase::Commit);
363 } 409 }
364 410
365 bool QuotaDatabase::FindOriginUsedCount( 411 bool QuotaDatabase::FindOriginUsedCount(
366 const GURL& origin, StorageType type, int* used_count) { 412 const GURL& origin, StorageType type, int* used_count) {
367 DCHECK(used_count); 413 DCHECK(used_count);
368 if (!LazyOpen(false)) 414 if (!LazyOpen(false))
369 return false; 415 return false;
370 416
371 const char* kSql = 417 const char* kSql =
372 "SELECT used_count FROM OriginLastAccessTable" 418 "SELECT used_count FROM OriginInfoTable"
373 " WHERE origin = ? AND type = ?"; 419 " WHERE origin = ? AND type = ?";
374 420
375 sql::Statement statement; 421 sql::Statement statement;
376 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) 422 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
377 return false; 423 return false;
378 424
379 statement.BindString(0, origin.spec()); 425 statement.BindString(0, origin.spec());
380 statement.BindInt(1, static_cast<int>(type)); 426 statement.BindInt(1, static_cast<int>(type));
381 if (!statement.Step() || !statement.Succeeded()) 427 if (!statement.Step() || !statement.Succeeded())
382 return false; 428 return false;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 return false; 468 return false;
423 } 469 }
424 470
425 // Start a long-running transaction. 471 // Start a long-running transaction.
426 db_->BeginTransaction(); 472 db_->BeginTransaction();
427 473
428 return true; 474 return true;
429 } 475 }
430 476
431 bool QuotaDatabase::EnsureDatabaseVersion() { 477 bool QuotaDatabase::EnsureDatabaseVersion() {
478 static const size_t kTableCount = ARRAYSIZE_UNSAFE(kTables);
479 static const size_t kIndexCount = ARRAYSIZE_UNSAFE(kIndexes);
432 if (!sql::MetaTable::DoesTableExist(db_.get())) 480 if (!sql::MetaTable::DoesTableExist(db_.get()))
433 return CreateSchema(); 481 return CreateSchema(db_.get(), meta_table_.get(),
482 kCurrentVersion, kCompatibleVersion,
483 kTables, kTableCount,
484 kIndexes, kIndexCount);
434 485
435 if (!meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion)) 486 if (!meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion))
436 return false; 487 return false;
437 488
438 if (meta_table_->GetCompatibleVersionNumber() > kCurrentVersion) { 489 if (meta_table_->GetCompatibleVersionNumber() > kCurrentVersion) {
439 LOG(WARNING) << "Quota database is too new."; 490 LOG(WARNING) << "Quota database is too new.";
440 return false; 491 return false;
441 } 492 }
442 493
443 if (meta_table_->GetVersionNumber() < kCurrentVersion) { 494 if (meta_table_->GetVersionNumber() < kCurrentVersion) {
444 // TODO(kinuko): Support schema upgrade. 495 if (!UpgradeSchema(meta_table_->GetVersionNumber()))
445 return ResetSchema(); 496 return ResetSchema();
446 } 497 }
447 498
448 #ifndef NDEBUG 499 #ifndef NDEBUG
449 DCHECK(sql::MetaTable::DoesTableExist(db_.get())); 500 DCHECK(sql::MetaTable::DoesTableExist(db_.get()));
450 for (int i = 0; i < kTableCount; ++i) { 501 for (size_t i = 0; i < kTableCount; ++i) {
451 DCHECK(db_->DoesTableExist(kTables[i].table_name)); 502 DCHECK(db_->DoesTableExist(kTables[i].table_name));
452 } 503 }
453 #endif 504 #endif
454 505
455 return true; 506 return true;
456 } 507 }
457 508
458 bool QuotaDatabase::CreateSchema() { 509 // static
510 bool QuotaDatabase::CreateSchema(
511 sql::Connection* database,
512 sql::MetaTable* meta_table,
513 int schema_version, int compatible_version,
514 const TableSchema* tables, size_t tables_size,
515 const IndexSchema* indexes, size_t indexes_size) {
459 // TODO(kinuko): Factor out the common code to create databases. 516 // TODO(kinuko): Factor out the common code to create databases.
460 sql::Transaction transaction(db_.get()); 517 sql::Transaction transaction(database);
461 if (!transaction.Begin()) 518 if (!transaction.Begin())
462 return false; 519 return false;
463 520
464 if (!meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion)) 521 if (!meta_table->Init(database, schema_version, compatible_version))
465 return false; 522 return false;
466 523
467 for (int i = 0; i < kTableCount; ++i) { 524 for (size_t i = 0; i < tables_size; ++i) {
468 std::string sql("CREATE TABLE "); 525 std::string sql("CREATE TABLE ");
469 sql += kTables[i].table_name; 526 sql += tables[i].table_name;
470 sql += kTables[i].columns; 527 sql += tables[i].columns;
471 if (!db_->Execute(sql.c_str())) { 528 if (!database->Execute(sql.c_str())) {
472 VLOG(1) << "Failed to execute " << sql; 529 VLOG(1) << "Failed to execute " << sql;
473 return false; 530 return false;
474 } 531 }
475 } 532 }
476 533
477 for (int i = 0; i < kIndexCount; ++i) { 534 for (size_t i = 0; i < indexes_size; ++i) {
478 std::string sql; 535 std::string sql;
479 if (kIndexes[i].unique) 536 if (indexes[i].unique)
480 sql += "CREATE UNIQUE INDEX "; 537 sql += "CREATE UNIQUE INDEX ";
481 else 538 else
482 sql += "CREATE INDEX "; 539 sql += "CREATE INDEX ";
483 sql += kIndexes[i].index_name; 540 sql += indexes[i].index_name;
484 sql += " ON "; 541 sql += " ON ";
485 sql += kIndexes[i].table_name; 542 sql += indexes[i].table_name;
486 sql += kIndexes[i].columns; 543 sql += indexes[i].columns;
487 if (!db_->Execute(sql.c_str())) { 544 if (!database->Execute(sql.c_str())) {
488 VLOG(1) << "Failed to execute " << sql; 545 VLOG(1) << "Failed to execute " << sql;
489 return false; 546 return false;
490 } 547 }
491 } 548 }
492 549
493 return transaction.Commit(); 550 return transaction.Commit();
494 } 551 }
495 552
496 bool QuotaDatabase::ResetSchema() { 553 bool QuotaDatabase::ResetSchema() {
497 DCHECK(!db_file_path_.empty()); 554 DCHECK(!db_file_path_.empty());
(...skipping 11 matching lines...) Expand all
509 return false; 566 return false;
510 567
511 // So we can't go recursive. 568 // So we can't go recursive.
512 if (is_recreating_) 569 if (is_recreating_)
513 return false; 570 return false;
514 571
515 AutoReset<bool> auto_reset(&is_recreating_, true); 572 AutoReset<bool> auto_reset(&is_recreating_, true);
516 return LazyOpen(true); 573 return LazyOpen(true);
517 } 574 }
518 575
576 bool QuotaDatabase::UpgradeSchema(int current_version) {
577 if (current_version == 2) {
578 QuotaTableImporter importer;
579 typedef std::vector<QuotaTableEntry> QuotaTableEntries;
580 if (!DumpQuotaTable(new QuotaTableCallback(base::Bind(
581 &QuotaTableImporter::Append, base::Unretained(&importer)))))
582 return false;
583 ResetSchema();
584 for (QuotaTableEntries::const_iterator iter = importer.entries.begin();
585 iter != importer.entries.end(); ++iter) {
586 if (!SetHostQuota(iter->host, iter->type, iter->quota))
587 return false;
588 }
589 Commit();
590 return true;
591 }
592 return false;
593 }
594
519 bool QuotaDatabase::DumpQuotaTable(QuotaTableCallback* callback) { 595 bool QuotaDatabase::DumpQuotaTable(QuotaTableCallback* callback) {
520 scoped_ptr<QuotaTableCallback> callback_deleter(callback); 596 scoped_ptr<QuotaTableCallback> callback_deleter(callback);
521 if (!LazyOpen(true)) 597 if (!LazyOpen(true))
522 return false; 598 return false;
523 599
524 const char* kSql = "SELECT * FROM HostQuotaTable"; 600 const char* kSql = "SELECT * FROM HostQuotaTable";
525 sql::Statement statement; 601 sql::Statement statement;
526 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) 602 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
527 return false; 603 return false;
528 604
529 while (statement.Step()) { 605 while (statement.Step()) {
530 QuotaTableEntry entry = { 606 QuotaTableEntry entry = {
531 statement.ColumnString(0), 607 statement.ColumnString(0),
532 static_cast<StorageType>(statement.ColumnInt(1)), 608 static_cast<StorageType>(statement.ColumnInt(1)),
533 statement.ColumnInt64(2) 609 statement.ColumnInt64(2)
534 }; 610 };
535 611
536 if (!callback->Run(entry)) 612 if (!callback->Run(entry))
537 return true; 613 return true;
538 } 614 }
539 615
540 return statement.Succeeded(); 616 return statement.Succeeded();
541 } 617 }
542 618
543 bool QuotaDatabase::DumpLastAccessTimeTable( 619 bool QuotaDatabase::DumpOriginInfoTable(
544 LastAccessTimeTableCallback* callback) { 620 OriginInfoTableCallback* callback) {
545 scoped_ptr<LastAccessTimeTableCallback> callback_deleter(callback); 621 scoped_ptr<OriginInfoTableCallback> callback_deleter(callback);
546 622
547 if (!LazyOpen(true)) 623 if (!LazyOpen(true))
548 return false; 624 return false;
549 625
550 const char* kSql = "SELECT * FROM OriginLastAccessTable"; 626 const char* kSql = "SELECT * FROM OriginInfoTable";
551 sql::Statement statement; 627 sql::Statement statement;
552 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) 628 if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
553 return false; 629 return false;
554 630
555 while (statement.Step()) { 631 while (statement.Step()) {
556 LastAccessTimeTableEntry entry = { 632 OriginInfoTableEntry entry = {
557 GURL(statement.ColumnString(0)), 633 GURL(statement.ColumnString(0)),
558 static_cast<StorageType>(statement.ColumnInt(1)), 634 static_cast<StorageType>(statement.ColumnInt(1)),
559 statement.ColumnInt(2), 635 statement.ColumnInt(2),
560 base::Time::FromInternalValue(statement.ColumnInt64(3)) 636 base::Time::FromInternalValue(statement.ColumnInt64(3)),
637 base::Time::FromInternalValue(statement.ColumnInt64(4))
561 }; 638 };
562 639
563 if (!callback->Run(entry)) 640 if (!callback->Run(entry))
564 return true; 641 return true;
565 } 642 }
566 643
567 return statement.Succeeded(); 644 return statement.Succeeded();
568 } 645 }
569 646
570 bool operator<(const QuotaDatabase::QuotaTableEntry& lhs, 647 bool operator<(const QuotaDatabase::QuotaTableEntry& lhs,
571 const QuotaDatabase::QuotaTableEntry& rhs) { 648 const QuotaDatabase::QuotaTableEntry& rhs) {
572 if (lhs.host < rhs.host) return true; 649 if (lhs.host < rhs.host) return true;
573 if (rhs.host < lhs.host) return false; 650 if (rhs.host < lhs.host) return false;
574 if (lhs.type < rhs.type) return true; 651 if (lhs.type < rhs.type) return true;
575 if (rhs.type < lhs.type) return false; 652 if (rhs.type < lhs.type) return false;
576 return lhs.quota < rhs.quota; 653 return lhs.quota < rhs.quota;
577 } 654 }
578 655
579 bool operator<(const QuotaDatabase::LastAccessTimeTableEntry& lhs, 656 bool operator<(const QuotaDatabase::OriginInfoTableEntry& lhs,
580 const QuotaDatabase::LastAccessTimeTableEntry& rhs) { 657 const QuotaDatabase::OriginInfoTableEntry& rhs) {
581 if (lhs.origin < rhs.origin) return true; 658 if (lhs.origin < rhs.origin) return true;
582 if (rhs.origin < lhs.origin) return false; 659 if (rhs.origin < lhs.origin) return false;
583 if (lhs.type < rhs.type) return true; 660 if (lhs.type < rhs.type) return true;
584 if (rhs.type < lhs.type) return false; 661 if (rhs.type < lhs.type) return false;
585 if (lhs.used_count < rhs.used_count) return true; 662 if (lhs.used_count < rhs.used_count) return true;
586 if (rhs.used_count < lhs.used_count) return false; 663 if (rhs.used_count < lhs.used_count) return false;
587 return lhs.last_access_time < rhs.last_access_time; 664 return lhs.last_access_time < rhs.last_access_time;
588 } 665 }
666
589 } // quota namespace 667 } // 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