| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/predictors/resource_prefetch_predictor_tables.h" | 5 #include "chrome/browser/predictors/resource_prefetch_predictor_tables.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <memory> | 10 #include <memory> |
| 11 #include <utility> | 11 #include <utility> |
| 12 | 12 |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
| 16 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
| 17 #include "sql/meta_table.h" |
| 17 #include "sql/statement.h" | 18 #include "sql/statement.h" |
| 19 #include "sql/transaction.h" |
| 18 | 20 |
| 19 using content::BrowserThread; | 21 using content::BrowserThread; |
| 20 using sql::Statement; | 22 using sql::Statement; |
| 21 | 23 |
| 22 namespace { | 24 namespace { |
| 23 | 25 |
| 24 using ResourceRow = predictors::ResourcePrefetchPredictorTables::ResourceRow; | 26 using ResourceRow = predictors::ResourcePrefetchPredictorTables::ResourceRow; |
| 25 | 27 |
| 28 const char kMetadataTableName[] = "resource_prefetch_predictor_metadata"; |
| 26 const char kUrlResourceTableName[] = "resource_prefetch_predictor_url"; | 29 const char kUrlResourceTableName[] = "resource_prefetch_predictor_url"; |
| 27 const char kUrlMetadataTableName[] = "resource_prefetch_predictor_url_metadata"; | 30 const char kUrlMetadataTableName[] = "resource_prefetch_predictor_url_metadata"; |
| 28 const char kHostResourceTableName[] = "resource_prefetch_predictor_host"; | 31 const char kHostResourceTableName[] = "resource_prefetch_predictor_host"; |
| 29 const char kHostMetadataTableName[] = | 32 const char kHostMetadataTableName[] = |
| 30 "resource_prefetch_predictor_host_metadata"; | 33 "resource_prefetch_predictor_host_metadata"; |
| 31 | 34 |
| 35 const char kCreateGlobalMetadataStatementTemplate[] = |
| 36 "CREATE TABLE %s ( " |
| 37 "key TEXT, value INTEGER, " |
| 38 "PRIMARY KEY (key))"; |
| 39 const char kCreateResourceTableStatementTemplate[] = |
| 40 "CREATE TABLE %s ( " |
| 41 "main_page_url TEXT, " |
| 42 "resource_url TEXT, " |
| 43 "proto BLOB, " |
| 44 "PRIMARY KEY(main_page_url, resource_url))"; |
| 45 const char kCreateMetadataTableStatementTemplate[] = |
| 46 "CREATE TABLE %s ( " |
| 47 "main_page_url TEXT, " |
| 48 "last_visit_time INTEGER, " |
| 49 "PRIMARY KEY(main_page_url))"; |
| 50 |
| 32 const char kInsertResourceTableStatementTemplate[] = | 51 const char kInsertResourceTableStatementTemplate[] = |
| 33 "INSERT INTO %s (main_page_url, resource_url, proto) VALUES (?,?,?)"; | 52 "INSERT INTO %s (main_page_url, resource_url, proto) VALUES (?,?,?)"; |
| 34 const char kInsertMetadataTableStatementTemplate[] = | 53 const char kInsertMetadataTableStatementTemplate[] = |
| 35 "INSERT INTO %s (main_page_url, last_visit_time) VALUES (?,?)"; | 54 "INSERT INTO %s (main_page_url, last_visit_time) VALUES (?,?)"; |
| 36 const char kDeleteStatementTemplate[] = "DELETE FROM %s WHERE main_page_url=?"; | 55 const char kDeleteStatementTemplate[] = "DELETE FROM %s WHERE main_page_url=?"; |
| 37 | 56 |
| 38 void BindResourceRowToStatement(const ResourceRow& row, | 57 void BindResourceRowToStatement(const ResourceRow& row, |
| 39 const std::string& primary_key, | 58 const std::string& primary_key, |
| 40 Statement* statement) { | 59 Statement* statement) { |
| 41 chrome_browser_predictors::ResourceData proto; | 60 chrome_browser_predictors::ResourceData proto; |
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 return false; | 447 return false; |
| 429 | 448 |
| 430 for (ResourceRows::const_iterator it = data.resources.begin(); | 449 for (ResourceRows::const_iterator it = data.resources.begin(); |
| 431 it != data.resources.end(); ++it) { | 450 it != data.resources.end(); ++it) { |
| 432 if (it->resource_url.spec().length() > kMaxStringLength) | 451 if (it->resource_url.spec().length() > kMaxStringLength) |
| 433 return false; | 452 return false; |
| 434 } | 453 } |
| 435 return true; | 454 return true; |
| 436 } | 455 } |
| 437 | 456 |
| 457 // static |
| 438 bool ResourcePrefetchPredictorTables::DropTablesIfOutdated( | 458 bool ResourcePrefetchPredictorTables::DropTablesIfOutdated( |
| 439 sql::Connection* db) { | 459 sql::Connection* db) { |
| 460 int version = GetDatabaseVersion(db); |
| 440 bool success = true; | 461 bool success = true; |
| 441 for (const char* table_name : | 462 // Too new is also a problem. |
| 442 {kUrlResourceTableName, kHostResourceTableName}) { | 463 bool incompatible_version = version != kDatabaseVersion; |
| 443 if (db->DoesTableExist(table_name) && | 464 |
| 444 !db->DoesColumnExist(table_name, "proto")) { | 465 if (incompatible_version) { |
| 445 success &= | 466 for (const char* table_name : |
| 446 db->Execute(base::StringPrintf("DROP TABLE %s", table_name).c_str()); | 467 {kMetadataTableName, kUrlResourceTableName, kHostResourceTableName, |
| 468 kUrlMetadataTableName, kHostMetadataTableName}) { |
| 469 success = |
| 470 success && |
| 471 db->Execute(base::StringPrintf("DROP TABLE IF EXISTS %s", table_name) |
| 472 .c_str()); |
| 447 } | 473 } |
| 448 } | 474 } |
| 475 |
| 476 if (incompatible_version) { |
| 477 success = |
| 478 success && |
| 479 db->Execute(base::StringPrintf(kCreateGlobalMetadataStatementTemplate, |
| 480 kMetadataTableName) |
| 481 .c_str()); |
| 482 success = success && SetDatabaseVersion(db, kDatabaseVersion); |
| 483 } |
| 484 |
| 449 return success; | 485 return success; |
| 450 } | 486 } |
| 451 | 487 |
| 488 // static |
| 489 int ResourcePrefetchPredictorTables::GetDatabaseVersion(sql::Connection* db) { |
| 490 int version = 0; |
| 491 if (db->DoesTableExist(kMetadataTableName)) { |
| 492 sql::Statement statement(db->GetUniqueStatement( |
| 493 base::StringPrintf("SELECT value FROM %s WHERE key='version'", |
| 494 kMetadataTableName) |
| 495 .c_str())); |
| 496 if (statement.Step()) |
| 497 version = statement.ColumnInt(0); |
| 498 } |
| 499 return version; |
| 500 } |
| 501 |
| 502 // static |
| 503 bool ResourcePrefetchPredictorTables::SetDatabaseVersion(sql::Connection* db, |
| 504 int version) { |
| 505 sql::Statement statement(db->GetUniqueStatement( |
| 506 base::StringPrintf( |
| 507 "INSERT OR REPLACE INTO %s (key,value) VALUES ('version',%d)", |
| 508 kMetadataTableName, version) |
| 509 .c_str())); |
| 510 return statement.Run(); |
| 511 } |
| 512 |
| 452 void ResourcePrefetchPredictorTables::CreateTableIfNonExistent() { | 513 void ResourcePrefetchPredictorTables::CreateTableIfNonExistent() { |
| 453 DCHECK_CURRENTLY_ON(BrowserThread::DB); | 514 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 454 if (CantAccessDatabase()) | 515 if (CantAccessDatabase()) |
| 455 return; | 516 return; |
| 456 | 517 |
| 457 const char resource_table_creator[] = | 518 // Database initialization is all-or-nothing. |
| 458 "CREATE TABLE %s ( " | 519 sql::Connection* db = DB(); |
| 459 "main_page_url TEXT, " | 520 sql::Transaction transaction{db}; |
| 460 "resource_url TEXT, " | 521 bool success = transaction.Begin(); |
| 461 "proto BLOB, " | |
| 462 "PRIMARY KEY(main_page_url, resource_url))"; | |
| 463 const char* metadata_table_creator = | |
| 464 "CREATE TABLE %s ( " | |
| 465 "main_page_url TEXT, " | |
| 466 "last_visit_time INTEGER, " | |
| 467 "PRIMARY KEY(main_page_url))"; | |
| 468 | 522 |
| 469 sql::Connection* db = DB(); | 523 success = success && DropTablesIfOutdated(db); |
| 470 bool success = DropTablesIfOutdated(db) && | 524 |
| 471 (db->DoesTableExist(kUrlResourceTableName) || | 525 success = |
| 472 db->Execute(base::StringPrintf(resource_table_creator, | 526 success && |
| 473 kUrlResourceTableName) | 527 (db->DoesTableExist(kUrlResourceTableName) || |
| 474 .c_str())) && | 528 db->Execute(base::StringPrintf(kCreateResourceTableStatementTemplate, |
| 475 (db->DoesTableExist(kUrlMetadataTableName) || | 529 kUrlResourceTableName) |
| 476 db->Execute(base::StringPrintf(metadata_table_creator, | 530 .c_str())) && |
| 477 kUrlMetadataTableName) | 531 (db->DoesTableExist(kUrlMetadataTableName) || |
| 478 .c_str())) && | 532 db->Execute(base::StringPrintf(kCreateMetadataTableStatementTemplate, |
| 479 (db->DoesTableExist(kHostResourceTableName) || | 533 kUrlMetadataTableName) |
| 480 db->Execute(base::StringPrintf(resource_table_creator, | 534 .c_str())) && |
| 481 kHostResourceTableName) | 535 (db->DoesTableExist(kHostResourceTableName) || |
| 482 .c_str())) && | 536 db->Execute(base::StringPrintf(kCreateResourceTableStatementTemplate, |
| 483 (db->DoesTableExist(kHostMetadataTableName) || | 537 kHostResourceTableName) |
| 484 db->Execute(base::StringPrintf(metadata_table_creator, | 538 .c_str())) && |
| 485 kHostMetadataTableName) | 539 (db->DoesTableExist(kHostMetadataTableName) || |
| 486 .c_str())); | 540 db->Execute(base::StringPrintf(kCreateMetadataTableStatementTemplate, |
| 541 kHostMetadataTableName) |
| 542 .c_str())); |
| 543 |
| 544 if (success) |
| 545 success = transaction.Commit(); |
| 546 else |
| 547 transaction.Rollback(); |
| 487 | 548 |
| 488 if (!success) | 549 if (!success) |
| 489 ResetDB(); | 550 ResetDB(); |
| 490 } | 551 } |
| 491 | 552 |
| 492 void ResourcePrefetchPredictorTables::LogDatabaseStats() { | 553 void ResourcePrefetchPredictorTables::LogDatabaseStats() { |
| 493 DCHECK_CURRENTLY_ON(BrowserThread::DB); | 554 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 494 if (CantAccessDatabase()) | 555 if (CantAccessDatabase()) |
| 495 return; | 556 return; |
| 496 | 557 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 } | 627 } |
| 567 | 628 |
| 568 Statement* ResourcePrefetchPredictorTables::GetHostMetadataUpdateStatement() { | 629 Statement* ResourcePrefetchPredictorTables::GetHostMetadataUpdateStatement() { |
| 569 return new Statement(DB()->GetCachedStatement( | 630 return new Statement(DB()->GetCachedStatement( |
| 570 SQL_FROM_HERE, base::StringPrintf(kInsertMetadataTableStatementTemplate, | 631 SQL_FROM_HERE, base::StringPrintf(kInsertMetadataTableStatementTemplate, |
| 571 kHostMetadataTableName) | 632 kHostMetadataTableName) |
| 572 .c_str())); | 633 .c_str())); |
| 573 } | 634 } |
| 574 | 635 |
| 575 } // namespace predictors | 636 } // namespace predictors |
| OLD | NEW |