Chromium Code Reviews| 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_macros.h" | 14 #include "base/metrics/histogram_macros.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/meta_table.h" |
| 18 #include "sql/statement.h" | 18 #include "sql/statement.h" |
| 19 #include "sql/transaction.h" | 19 #include "sql/transaction.h" |
| 20 | 20 |
| 21 using content::BrowserThread; | 21 using content::BrowserThread; |
| 22 using sql::Statement; | 22 using sql::Statement; |
| 23 | 23 |
| 24 namespace { | 24 namespace { |
| 25 | 25 |
| 26 using ResourceRow = predictors::ResourcePrefetchPredictorTables::ResourceRow; | 26 using ResourceRow = predictors::ResourcePrefetchPredictorTables::ResourceRow; |
| 27 using RedirectStatRow = | |
| 28 predictors::ResourcePrefetchPredictorTables::RedirectStatRow; | |
| 27 | 29 |
| 28 const char kMetadataTableName[] = "resource_prefetch_predictor_metadata"; | 30 const char kMetadataTableName[] = "resource_prefetch_predictor_metadata"; |
| 29 const char kUrlResourceTableName[] = "resource_prefetch_predictor_url"; | 31 const char kUrlResourceTableName[] = "resource_prefetch_predictor_url"; |
| 30 const char kUrlMetadataTableName[] = "resource_prefetch_predictor_url_metadata"; | 32 const char kUrlMetadataTableName[] = "resource_prefetch_predictor_url_metadata"; |
| 31 const char kHostResourceTableName[] = "resource_prefetch_predictor_host"; | 33 const char kHostResourceTableName[] = "resource_prefetch_predictor_host"; |
| 32 const char kHostMetadataTableName[] = | 34 const char kHostMetadataTableName[] = |
| 33 "resource_prefetch_predictor_host_metadata"; | 35 "resource_prefetch_predictor_host_metadata"; |
| 34 | 36 |
| 35 const char kCreateGlobalMetadataStatementTemplate[] = | 37 const char kCreateGlobalMetadataStatementTemplate[] = |
| 36 "CREATE TABLE %s ( " | 38 "CREATE TABLE %s ( " |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 61 row.ToProto(&proto); | 63 row.ToProto(&proto); |
| 62 int size = proto.ByteSize(); | 64 int size = proto.ByteSize(); |
| 63 std::vector<char> proto_buffer(size); | 65 std::vector<char> proto_buffer(size); |
| 64 proto.SerializeToArray(&proto_buffer[0], size); | 66 proto.SerializeToArray(&proto_buffer[0], size); |
| 65 | 67 |
| 66 statement->BindString(0, primary_key); | 68 statement->BindString(0, primary_key); |
| 67 statement->BindString(1, row.resource_url.spec()); | 69 statement->BindString(1, row.resource_url.spec()); |
| 68 statement->BindBlob(2, &proto_buffer[0], size); | 70 statement->BindBlob(2, &proto_buffer[0], size); |
| 69 } | 71 } |
| 70 | 72 |
| 73 void BindRedirectStatRowToStatement(const RedirectStatRow& row, | |
| 74 const std::string& primary_key, | |
| 75 Statement* statement) { | |
| 76 | |
| 77 } | |
| 78 | |
| 71 bool StepAndInitializeResourceRow(Statement* statement, | 79 bool StepAndInitializeResourceRow(Statement* statement, |
| 72 ResourceRow* row, | 80 ResourceRow* row, |
| 73 std::string* primary_key) { | 81 std::string* primary_key) { |
| 74 if (!statement->Step()) | 82 if (!statement->Step()) |
| 75 return false; | 83 return false; |
| 76 | 84 |
| 77 *primary_key = statement->ColumnString(0); | 85 *primary_key = statement->ColumnString(0); |
| 78 | 86 |
| 79 int size = statement->ColumnByteLength(2); | 87 int size = statement->ColumnByteLength(2); |
| 80 const void* data = statement->ColumnBlob(2); | 88 const void* data = statement->ColumnBlob(2); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 224 | 232 |
| 225 ResourcePrefetchPredictorTables::PrefetchData::~PrefetchData() { | 233 ResourcePrefetchPredictorTables::PrefetchData::~PrefetchData() { |
| 226 } | 234 } |
| 227 | 235 |
| 228 bool ResourcePrefetchPredictorTables::PrefetchData::operator==( | 236 bool ResourcePrefetchPredictorTables::PrefetchData::operator==( |
| 229 const PrefetchData& rhs) const { | 237 const PrefetchData& rhs) const { |
| 230 return key_type == rhs.key_type && primary_key == rhs.primary_key && | 238 return key_type == rhs.key_type && primary_key == rhs.primary_key && |
| 231 resources == rhs.resources; | 239 resources == rhs.resources; |
| 232 } | 240 } |
| 233 | 241 |
| 242 RedirectStatRow::RedirectStatRow() | |
| 243 : number_of_hits(0), | |
| 244 number_of_misses(0), | |
| 245 consecutive_misses(0) {} | |
| 246 | |
| 247 RedirectStatRow::RedirectStatRow(const RedirectStatRow& other) | |
| 248 : final_redirect(other.final_redirect), | |
| 249 number_of_hits(other.number_of_hits), | |
| 250 number_of_misses(other.number_of_misses), | |
| 251 consecutive_misses(other.consecutive_misses) {} | |
| 252 | |
| 253 ResourcePrefetchPredictorTables::RedirectData::RedirectData( | |
| 254 PrefetchKeyType i_key_type, | |
| 255 const std::string& i_primary_key) | |
| 256 : key_type(i_key_type), | |
| 257 primary_key(i_primary_key) {} | |
| 258 | |
| 259 ResourcePrefetchPredictorTables::RedirectData::RedirectData( | |
| 260 const RedirectData& other) | |
| 261 : key_type(other.key_type), | |
| 262 primary_key(other.primary_key), | |
| 263 last_visit(other.last_visit), | |
| 264 redirect_stats(other.redirect_stats) {} | |
| 265 | |
| 266 ResourcePrefetchPredictorTables::RedirectData::~RedirectData() { | |
| 267 } | |
| 268 | |
| 234 void ResourcePrefetchPredictorTables::GetAllData( | 269 void ResourcePrefetchPredictorTables::GetAllData( |
| 235 PrefetchDataMap* url_data_map, | 270 PrefetchDataMap* url_data_map, |
| 236 PrefetchDataMap* host_data_map) { | 271 PrefetchDataMap* host_data_map, |
| 272 RedirectDataMap* url_redirect_data_map, | |
| 273 RedirectDataMap* host_redirect_data_map) { | |
| 237 DCHECK_CURRENTLY_ON(BrowserThread::DB); | 274 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 238 if (CantAccessDatabase()) | 275 if (CantAccessDatabase()) |
| 239 return; | 276 return; |
| 240 | 277 |
| 241 DCHECK(url_data_map); | 278 DCHECK(url_data_map); |
| 242 DCHECK(host_data_map); | 279 DCHECK(host_data_map); |
| 280 DCHECK(url_redirect_data_map); | |
| 281 DCHECK(host_redirect_data_map); | |
| 243 url_data_map->clear(); | 282 url_data_map->clear(); |
| 244 host_data_map->clear(); | 283 host_data_map->clear(); |
| 284 url_redirect_data_map->clear(); | |
| 285 host_redirect_data_map->clear(); | |
| 245 | 286 |
| 246 std::vector<std::string> urls_to_delete, hosts_to_delete; | 287 std::vector<std::string> urls_to_delete, hosts_to_delete; |
| 247 GetAllDataHelper(PREFETCH_KEY_TYPE_URL, url_data_map, &urls_to_delete); | 288 GetAllDataHelper(PREFETCH_KEY_TYPE_URL, url_data_map, &urls_to_delete); |
| 248 GetAllDataHelper(PREFETCH_KEY_TYPE_HOST, host_data_map, &hosts_to_delete); | 289 GetAllDataHelper(PREFETCH_KEY_TYPE_HOST, host_data_map, &hosts_to_delete); |
| 290 // TODO: get data from redirect tables | |
| 249 | 291 |
| 250 if (!urls_to_delete.empty() || !hosts_to_delete.empty()) | 292 if (!urls_to_delete.empty() || !hosts_to_delete.empty()) |
| 251 DeleteData(urls_to_delete, hosts_to_delete); | 293 DeleteData(urls_to_delete, hosts_to_delete); |
| 252 } | 294 } |
| 253 | 295 |
| 254 void ResourcePrefetchPredictorTables::UpdateData( | 296 void ResourcePrefetchPredictorTables::UpdatePrefetchData( |
| 255 const PrefetchData& url_data, | 297 const PrefetchData& url_data, |
| 256 const PrefetchData& host_data) { | 298 const PrefetchData& host_data) { |
| 257 DCHECK_CURRENTLY_ON(BrowserThread::DB); | 299 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 258 if (CantAccessDatabase()) | 300 if (CantAccessDatabase()) |
| 259 return; | 301 return; |
| 260 | 302 |
| 261 DCHECK(!url_data.is_host() && host_data.is_host()); | 303 DCHECK(!url_data.is_host() && host_data.is_host()); |
| 262 DCHECK(!url_data.primary_key.empty() || !host_data.primary_key.empty()); | 304 DCHECK(!url_data.primary_key.empty() || !host_data.primary_key.empty()); |
| 263 | 305 |
| 264 DB()->BeginTransaction(); | 306 DB()->BeginTransaction(); |
| 265 | 307 |
| 266 bool success = (url_data.primary_key.empty() || UpdateDataHelper(url_data)) && | 308 bool success = |
| 309 (url_data.primary_key.empty() || UpdatePrefetchDataHelper(url_data)) && | |
| 267 (host_data.primary_key.empty() || UpdateDataHelper(host_data)); | 310 (host_data.primary_key.empty() || UpdateDataHelper(host_data)); |
| 268 if (!success) | 311 if (!success) |
| 269 DB()->RollbackTransaction(); | 312 DB()->RollbackTransaction(); |
| 270 | 313 |
| 271 DB()->CommitTransaction(); | 314 DB()->CommitTransaction(); |
| 272 } | 315 } |
| 273 | 316 |
| 317 void ResourcePrefetchPredictorTables::UpdateRedirectData( | |
| 318 const RedirectData& redirect_data) { | |
| 319 DCHECK_CURRENTLY_ON(BrowserThread::DB); | |
| 320 if (CantAccessDatabase()) | |
| 321 return; | |
| 322 | |
| 323 DB()->BeginTransaction(); | |
| 324 | |
| 325 bool success = UpdateRedirectDataHelper(redirect_data); | |
| 326 if (!success) | |
| 327 DB()->RollbackTransaction(); | |
| 328 | |
| 329 DB()->CommitTransaction(); | |
| 330 } | |
| 331 | |
| 274 void ResourcePrefetchPredictorTables::DeleteData( | 332 void ResourcePrefetchPredictorTables::DeleteData( |
| 275 const std::vector<std::string>& urls, | 333 const std::vector<std::string>& urls, |
| 276 const std::vector<std::string>& hosts) { | 334 const std::vector<std::string>& hosts) { |
| 277 DCHECK_CURRENTLY_ON(BrowserThread::DB); | 335 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 278 if (CantAccessDatabase()) | 336 if (CantAccessDatabase()) |
| 279 return; | 337 return; |
| 280 | 338 |
| 281 DCHECK(!urls.empty() || !hosts.empty()); | 339 DCHECK(!urls.empty() || !hosts.empty()); |
| 282 | 340 |
| 283 if (!urls.empty()) | 341 if (!urls.empty()) |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 357 PrefetchDataMap::iterator it = data_map->find(primary_key); | 415 PrefetchDataMap::iterator it = data_map->find(primary_key); |
| 358 if (it != data_map->end()) { | 416 if (it != data_map->end()) { |
| 359 int64_t last_visit = metadata_reader.ColumnInt64(1); | 417 int64_t last_visit = metadata_reader.ColumnInt64(1); |
| 360 it->second.last_visit = base::Time::FromInternalValue(last_visit); | 418 it->second.last_visit = base::Time::FromInternalValue(last_visit); |
| 361 } else { | 419 } else { |
| 362 to_delete->push_back(primary_key); | 420 to_delete->push_back(primary_key); |
| 363 } | 421 } |
| 364 } | 422 } |
| 365 } | 423 } |
| 366 | 424 |
| 367 bool ResourcePrefetchPredictorTables::UpdateDataHelper( | 425 bool ResourcePrefetchPredictorTables::UpdatePrefetchDataHelper( |
| 368 const PrefetchData& data) { | 426 const PrefetchData& data) { |
| 369 DCHECK(!data.primary_key.empty()); | 427 DCHECK(!data.primary_key.empty()); |
| 370 | 428 |
| 371 if (!StringsAreSmallerThanDBLimit(data)) { | 429 if (!StringsAreSmallerThanDBLimit(data)) { |
| 372 UMA_HISTOGRAM_BOOLEAN("ResourcePrefetchPredictor.DbStringTooLong", true); | 430 UMA_HISTOGRAM_BOOLEAN("ResourcePrefetchPredictor.DbStringTooLong", true); |
| 373 return false; | 431 return false; |
| 374 } | 432 } |
| 375 | 433 |
| 376 // Delete the older data from both the tables. | 434 // Delete the older data from both the tables. |
| 377 std::unique_ptr<Statement> deleter(data.is_host() | 435 std::unique_ptr<Statement> deleter(data.is_host() |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 402 data.is_host() ? GetHostMetadataUpdateStatement() | 460 data.is_host() ? GetHostMetadataUpdateStatement() |
| 403 : GetUrlMetadataUpdateStatement()); | 461 : GetUrlMetadataUpdateStatement()); |
| 404 metadata_inserter->BindString(0, data.primary_key); | 462 metadata_inserter->BindString(0, data.primary_key); |
| 405 metadata_inserter->BindInt64(1, data.last_visit.ToInternalValue()); | 463 metadata_inserter->BindInt64(1, data.last_visit.ToInternalValue()); |
| 406 if (!metadata_inserter->Run()) | 464 if (!metadata_inserter->Run()) |
| 407 return false; | 465 return false; |
| 408 | 466 |
| 409 return true; | 467 return true; |
| 410 } | 468 } |
| 411 | 469 |
| 470 bool ResourcePrefetchPredictorTables::UpdateRedirectDataHelper( | |
| 471 const RedirectData& data) { | |
| 472 DCHECK(!data.primary_key.empty()); | |
| 473 | |
| 474 if (!StringsAreSmallerThanDBLimit(data)) { | |
| 475 // TODO: UMA? | |
|
mattcary
2016/09/09 13:19:21
Yes!
| |
| 476 return false; | |
| 477 } | |
| 478 | |
| 479 // Delete the older data from the table. | |
| 480 std::unique_ptr<Statement> deleter(data.is_host() | |
| 481 ? GetHostRedirectStatDeleteStatement() | |
| 482 : GetUrlRedirectStatDeleteStatement()); | |
| 483 deleter->BindString(0, data.primary_key); | |
| 484 if (!deleter->Run()) | |
| 485 return false; | |
| 486 | |
| 487 // Add the new data to the table. | |
| 488 for (const RedirectStatRow& row : data.redirect_stats) { | |
| 489 std::unique_ptr<Statement> row_inserter( | |
| 490 data.is_host() ? GetHostRedirectStatUpdateStatement() | |
| 491 : GetUrlRedirectStatUpdateStatement()); | |
| 492 BindRedirectStatRowToStatement(row, data.primary_key, row_inserter.get()); | |
| 493 if (!row_inserter->Run()) | |
| 494 return false; | |
| 495 } | |
| 496 | |
| 497 return true; | |
| 498 } | |
| 499 | |
| 412 void ResourcePrefetchPredictorTables::DeleteDataHelper( | 500 void ResourcePrefetchPredictorTables::DeleteDataHelper( |
| 413 PrefetchKeyType key_type, | 501 PrefetchKeyType key_type, |
| 414 const std::vector<std::string>& keys) { | 502 const std::vector<std::string>& keys) { |
| 415 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST; | 503 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST; |
| 416 | 504 |
| 417 for (const std::string& key : keys) { | 505 for (const std::string& key : keys) { |
| 418 std::unique_ptr<Statement> deleter(is_host | 506 std::unique_ptr<Statement> deleter(is_host |
| 419 ? GetHostResourceDeleteStatement() | 507 ? GetHostResourceDeleteStatement() |
| 420 : GetUrlResourceDeleteStatement()); | 508 : GetUrlResourceDeleteStatement()); |
| 421 deleter->BindString(0, key); | 509 deleter->BindString(0, key); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 435 return false; | 523 return false; |
| 436 | 524 |
| 437 for (const ResourceRow& row : data.resources) { | 525 for (const ResourceRow& row : data.resources) { |
| 438 if (row.resource_url.spec().length() > kMaxStringLength) | 526 if (row.resource_url.spec().length() > kMaxStringLength) |
| 439 return false; | 527 return false; |
| 440 } | 528 } |
| 441 return true; | 529 return true; |
| 442 } | 530 } |
| 443 | 531 |
| 444 // static | 532 // static |
| 533 bool ResourcePrefetchPredictorTables::StringAreSmallerThanDBLimit( | |
| 534 const RedirectData& data) { | |
| 535 if (data.primary_key.length() > kMaxStringLength) | |
| 536 return false; | |
| 537 | |
| 538 for (const RedirectStatRow& row : data.redirect_stats) { | |
| 539 if (row.final_redirect.length() > kMaxStringLength) | |
| 540 return false; | |
| 541 } | |
| 542 return true; | |
| 543 } | |
| 544 | |
| 545 // static | |
| 445 bool ResourcePrefetchPredictorTables::DropTablesIfOutdated( | 546 bool ResourcePrefetchPredictorTables::DropTablesIfOutdated( |
| 446 sql::Connection* db) { | 547 sql::Connection* db) { |
| 447 int version = GetDatabaseVersion(db); | 548 int version = GetDatabaseVersion(db); |
| 448 bool success = true; | 549 bool success = true; |
| 449 // Too new is also a problem. | 550 // Too new is also a problem. |
| 450 bool incompatible_version = version != kDatabaseVersion; | 551 bool incompatible_version = version != kDatabaseVersion; |
| 451 | 552 |
| 452 if (incompatible_version) { | 553 if (incompatible_version) { |
| 453 for (const char* table_name : | 554 for (const char* table_name : |
| 454 {kMetadataTableName, kUrlResourceTableName, kHostResourceTableName, | 555 {kMetadataTableName, kUrlResourceTableName, kHostResourceTableName, |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 614 } | 715 } |
| 615 | 716 |
| 616 Statement* ResourcePrefetchPredictorTables::GetHostMetadataUpdateStatement() { | 717 Statement* ResourcePrefetchPredictorTables::GetHostMetadataUpdateStatement() { |
| 617 return new Statement(DB()->GetCachedStatement( | 718 return new Statement(DB()->GetCachedStatement( |
| 618 SQL_FROM_HERE, base::StringPrintf(kInsertMetadataTableStatementTemplate, | 719 SQL_FROM_HERE, base::StringPrintf(kInsertMetadataTableStatementTemplate, |
| 619 kHostMetadataTableName) | 720 kHostMetadataTableName) |
| 620 .c_str())); | 721 .c_str())); |
| 621 } | 722 } |
| 622 | 723 |
| 623 } // namespace predictors | 724 } // namespace predictors |
| OLD | NEW |